"""
*http server v2.0
*IO并发处理
*基本的request解析
*使用封装类
"""

from socket import *
from select import select


# 将具体http server功能封装
class HTTPServer:
    def __init__(self, server_address, static_dir):
        # 添加属性
        self.server_address = server_address
        self.static_dir = static_dir
        self.create_socket()
        self.bind()

    def create_socket(self):
        self.sockfd = socket()
        self.sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)

    def bind(self):
        self.sockfd.bind(self.server_address)
        self.ip = self.server_address[0]
        self.port = self.server_address[1]

    def serve_forever(self):
        self.sockfd.listen(5)
        print('Listen the port %d' % self.port)
        self.rlist = [self.sockfd]
        self.wlist = []
        self.xlist = []
        while True:
            rs, ws, xs = select(self.rlist, self.wlist, self.xlist)
            for r in rs:
                if r is self.sockfd:
                    c, addr = r.accept()
                    print('Connect from', addr)
                    self.rlist.append(c)
                else:
                    # 处理浏览器请求
                    self.handle(r)

    # 处理客户端请求
    def handle(self, connfd):
        # 接收客户端请求
        request = connfd.recv(4096)
        # 防止浏览器断开
        if not request:
            self.rlist.remove(connfd)
            connfd.close()
            return
        # print(request)
        request_line = request.splitlines()[0]
        info = request_line.decode().split(" ")[1]
        print(connfd.getpeername(), ":", info)
         # info 分为访问网页和其他
        if info == '/' or info[-5:] == '.html':
            self.get_html(connfd, info)
        else:
            self.get_data(connfd, info)

        # 结束本次请求
        self.rlist.remove(connfd)
        connfd.close()

    # 处理网页
    def get_html(self, connfd, info):
        if info == '/':
            filename = self.static_dir + "/index.html"
        else:
            filename = self.static_dir + info
        try:
            fd = open(filename, encoding='utf-8')
        except Exception:
            response_headers = "HTTP/1.1 404 Not Found\r\n"
            response_headers += '\r\n'
            response_body = '<h1>Sorry,Not found the page</h1>'
        else:
            response_headers = "HTTP/1.1 200 OK\r\n"
            response_headers += '\r\n'
            response_body = fd.read()
        finally:
            response = response_headers + response_body
            connfd.send(response.encode())

    # 其他情况
    def get_data(self, connfd, info):
        response_headers = "HTTP/1.1 200 OK\r\n"
        response_headers += '\r\n'
        response_body = '<h1>Waiting httpserver 3.0</h1>'
        response = response_headers + response_body
        connfd.send(response.encode())


# 如何使用HTTPServer类
if __name__ == "__main__":
    # 用户自己决定：地址、内容
    # 服务器地址
    server_addr = ('0.0.0.0', 8000)
    # 网页存放位置
    static_dir = "./static"
    # 生成实例对象
    httpd = HTTPServer(server_addr, static_dir)
    # 启动服务
    httpd.serve_forever()
